from PySide6.QtCore import QIODevice, QObject, QTimer, Slot, Signal, Property, QEnum, QThread
from PySide6.QtQml import QmlElement, QmlSingleton
from PySide6.QtSerialPort import QSerialPortInfo, QSerialPort
import logging
import threading
from enum import Enum
from .AdbWorker import AdbWorker
from PySide6.QtGui import QGuiApplication

# 定义 QML 模块名称和版本
QML_IMPORT_NAME = "ThreadedAdbClient"
QML_IMPORT_MAJOR_VERSION = 1

@QmlElement
class ThreadedAdbClient(QObject):

    _connectedStateChanged = Signal()
    
    # Signals to AdbWorker
    _connect = Signal()
    _disconnect = Signal()
    _update_install = Signal(str)
    _get_install_version = Signal()
    _get_ble_pairing_code = Signal()
    _set_ble_pairing_code = Signal()
    _kill_ros = Signal()
    _set_serial_number = Signal(int)
    _get_serial_number = Signal()
    
    # Signals from AdbWorker
    # connected = Signal()
    # disconnected = Signal()
    updateInstallFinished = Signal(bool, str)
    getInstallVersionFinished = Signal(bool, str)
    getBlePairingCodeFinished = Signal(bool, int)
    setBlePairingCodeFinished = Signal(bool, str)
    killRosFinished = Signal(bool)
    setSerialNumberFinished = Signal(bool, int)
    getSerialNumberFinished = Signal(bool, int)

    
    @Property(bool, notify=_connectedStateChanged)
    def connectedState(self):
        return self._connected
    
    def __init__(self, parent=None):
        super().__init__(parent)
        self._adbWorker = AdbWorker()
        self._workThread = QThread()
        self.app = QGuiApplication.instance()
        
        self._connected = False
        
        # 连接信号
        self._setup_signal_connections()
        
        # 保证线程在应用程序退出时正确退出
        self.app.aboutToQuit.connect(self._workThread.quit)
        
        self._adbWorker.moveToThread(self._workThread)
        self._workThread.start()
    
    def _setup_signal_connections(self):
        # worker signals to this class signals
        # self._adbWorker.connected.connect(self.connected)
        # self._adbWorker.disconnected.connect(self.disconnected)
        # self.connected.connect(self._connectedStateChanged)
        # self.disconnected.connect(self._connectedStateChanged)
        self._adbWorker.connected.connect(self._onConnected)
        self._adbWorker.disconnected.connect(self._onDisconnected)

        self._adbWorker.updateInstallFinished.connect(self.updateInstallFinished)
        self._adbWorker.getInstallVersionFinished.connect(self.getInstallVersionFinished)
        self._adbWorker.getBlePairingCodeFinished.connect(self.getBlePairingCodeFinished)
        self._adbWorker.setBlePairingCodeFinished.connect(self.setBlePairingCodeFinished)
        self._adbWorker.killRosFinished.connect(self.killRosFinished)
        self._adbWorker.setSerialNumberFinished.connect(self.setSerialNumberFinished)
        self._adbWorker.getSerialNumberFinished.connect(self.getSerialNumberFinished)
        
        # signals to worker slots
        self._connect.connect(self._adbWorker.connectDev)
        self._disconnect.connect(self._adbWorker.disconnect)
        self._update_install.connect(self._adbWorker.update_install)
        self._get_install_version.connect(self._adbWorker.get_install_version)
        self._get_ble_pairing_code.connect(self._adbWorker.get_ble_pairing_code)
        self._set_ble_pairing_code.connect(self._adbWorker.set_ble_pairing_code)
        self._kill_ros.connect(self._adbWorker.kill_ros)
        self._set_serial_number.connect(self._adbWorker.set_serial_number)
        self._get_serial_number.connect(self._adbWorker.get_serial_number)
        
        # 连接状态改变信号
    
    @Slot()
    def connectDev(self):
        self._connect.emit()

    @Slot()
    def disconnect(self):
        self._disconnect.emit()
    
    @Slot(str)
    def updateInstall(self, file_path: str):
        logging.info(f"update_install called in thread {threading.get_ident()}")
        self._update_install.emit(file_path)
    
    @Slot()
    def getInstallVersion(self):
        self._get_install_version.emit()
    
    @Slot()
    def getBlePairingCode(self):
        self._get_ble_pairing_code.emit()
    
    @Slot(int)
    def setBlePairingCode(self, code: int):
        self._set_ble_pairing_code.emit(code)
        
    @Slot()
    def killRos(self):
        self._kill_ros.emit()
        
    @Slot(int)
    def setSerialNumber(self, serialNumber: int):
        self._set_serial_number.emit(serialNumber)
    
    @Slot()
    def getSerialNumber(self):
        self._get_serial_number.emit()
        
    @Slot()
    def _onConnected(self):
        self._connected = True
        self._connectedStateChanged.emit()

    @Slot()
    def _onDisconnected(self):
        self._connected = False
        self._connectedStateChanged.emit()